2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import "AIActionDetailsPane.h"
18 #import "AIImageTextCellView.h"
19 #import "AIListObject.h"
20 #import "CSNewContactAlertWindowController.h"
21 #import "ESContactAlertsController.h"
22 #import "ESContactAlertsViewController.h"
24 #define NEW_ALERT_NIB @"NewAlert"
25 #define NEW_ALERT_NO_EVENTS_NIB @"NewAlertNoEvents"
27 @interface CSNewContactAlertWindowController (PRIVATE)
28 - (id)initWithWindowNibName:(NSString *)windowNibName
29 alert:(NSDictionary *)inAlert
30 forListObject:(AIListObject *)inListObject
31 notifyingTarget:(id)inTarget
32 delegate:(id)inDelegate
33 oldAlert:(id)inOldAlert
34 configureForGlobal:(BOOL)inConfigureForGlobal
35 defaultEventID:(NSString *)inDefaultEventID;
36 - (void)configureForEvent;
37 - (void)saveDetailsPaneChanges;
38 - (void)configureDetailsPane;
39 - (void)cleanUpDetailsPane;
41 - (void)updateHeaderView;
44 @implementation CSNewContactAlertWindowController
46 //Prompt for a new alert. Pass nil for a panel prompt.
47 + (void)editAlert:(NSDictionary *)inAlert forListObject:(AIListObject *)inObject onWindow:(NSWindow *)parentWindow notifyingTarget:(id)inTarget delegate:(id)inDelegate oldAlert:(id)inOldAlert configureForGlobal:(BOOL)inConfigureForGlobal defaultEventID:(NSString *)inDefaultEventID
49 CSNewContactAlertWindowController *newAlertwindow = [[self alloc] initWithWindowNibName:(/*showEventsInEditSheet ?
51 NEW_ALERT_NO_EVENTS_NIB)
53 forListObject:inObject
54 notifyingTarget:inTarget
57 configureForGlobal:inConfigureForGlobal
58 defaultEventID:inDefaultEventID];
61 [NSApp beginSheet:[newAlertwindow window]
62 modalForWindow:parentWindow
63 modalDelegate:newAlertwindow
64 didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
67 [newAlertwindow showWindow:nil];
72 - (id)initWithWindowNibName:(NSString *)windowNibName
73 alert:(NSDictionary *)inAlert
74 forListObject:(AIListObject *)inListObject
75 notifyingTarget:(id)inTarget
76 delegate:(id)inDelegate
77 oldAlert:(id)inOldAlert
78 configureForGlobal:(BOOL)inConfigureForGlobal
79 defaultEventID:(NSString *)inDefaultEventID
81 [super initWithWindowNibName:windowNibName];
84 oldAlert = [inOldAlert retain];
85 listObject = [inListObject retain];
87 delegate = inDelegate;
89 configureForGlobal = inConfigureForGlobal;
91 //Create a mutable copy of the alert dictionary we're passed. If we're passed nil, create the default alert.
92 alert = [inAlert mutableCopy];
96 defaultEventID = [[adium contactAlertsController] defaultEventID];
99 alert = [[NSMutableDictionary alloc] initWithObjectsAndKeys:inDefaultEventID, KEY_EVENT_ID,
100 [[adium contactAlertsController] defaultActionID], KEY_ACTION_ID, nil];
103 [[adium notificationCenter] addObserver:self
104 selector:@selector(alertDetailsForHeaderChanged:)
105 name:CONTACT_ALERTS_DETAILS_FOR_HEADER_CHANGED
114 [[adium notificationCenter] removeObserver:self];
118 [detailsPane release];
119 [listObject release];
124 //Setup the window before it is displayed
125 - (void)windowDidLoad
127 if ([[self superclass] instancesRespondToSelector:@selector(windowDidLoad)]){
128 [super windowDidLoad];
132 [[self window] center];
133 [popUp_event setMenu:[[adium contactAlertsController] menuOfEventsWithTarget:self forGlobalMenu:configureForGlobal]];
134 [popUp_action setMenu:[[adium contactAlertsController] menuOfActionsWithTarget:self]];
136 [[self window] setTitle:AILocalizedStringFromTable(@"New Alert", @"AdiumFramework", nil)];
138 [checkbox_oneTime setLocalizedString:AILocalizedStringFromTable(@"Delete after event occurs", @"AdiumFramework", "New contact alert pane")];
139 [button_OK setLocalizedString:AILocalizedStringFromTable(@"OK", @"AdiumFramework", nil)];
140 [button_cancel setLocalizedString:AILocalizedStringFromTable(@"Cancel", @"AdiumFramework", nil)];
142 [label_Event setLocalizedString:AILocalizedStringFromTable(@"Event:", @"AdiumFramework", "Label for contact alert event (e.g. Contact signed on, Message received, etc.)")];
143 [label_Action setLocalizedString:AILocalizedStringFromTable(@"Action:", @"AdiumFramework", "Label for contact alert action (e.g. Send message, Play sound, etc.)")];
145 //Remove the single-fire option for global
146 if(configureForGlobal){
147 if([checkbox_oneTime respondsToSelector:@selector(setHidden:)]){
148 [checkbox_oneTime setHidden:YES];
150 [checkbox_oneTime setFrame:NSZeroRect];
154 //Set things up for the current event
155 [self configureForEvent];
159 - (void)windowWillClose:(id)sender
161 [super windowWillClose:sender];
162 [self cleanUpDetailsPane];
165 //Called as the user list edit sheet closes, dismisses the sheet
166 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
168 [sheet orderOut:nil];
172 //Buttons --------------------------------------------------------------------------------------------------------------
175 - (IBAction)cancel:(id)sender
177 [self closeWindow:nil];
181 - (IBAction)save:(id)sender
183 //Save changes in our detail pane
184 [self saveDetailsPaneChanges];
186 //Pass the modified alert to our target
187 [target performSelector:@selector(alertUpdated:oldAlert:) withObject:alert withObject:oldAlert];
188 [self closeWindow:nil];
192 //Controls -------------------------------------------------------------------------------------------------------------
193 #pragma mark Controls
194 //Configure window for our current event dict
195 - (void)configureForEvent
197 NSEnumerator *enumerator;
198 NSMenuItem *menuItem;
200 //Select the correct event
201 NSString *eventID = [alert objectForKey:KEY_EVENT_ID];
202 enumerator = [[popUp_event itemArray] objectEnumerator];
203 while((menuItem = [enumerator nextObject])){
204 if([eventID isEqualToString:[menuItem representedObject]]){
205 [popUp_event selectItem:menuItem];
210 //Select the correct action
211 NSString *actionID = [alert objectForKey:KEY_ACTION_ID];
212 enumerator = [[popUp_action itemArray] objectEnumerator];
213 while((menuItem = [enumerator nextObject])){
214 if([actionID isEqualToString:[menuItem representedObject]]){
215 [popUp_action selectItem:menuItem];
220 //Setup our single-fire option
221 if(!configureForGlobal){
222 [checkbox_oneTime setState:[[alert objectForKey:KEY_ONE_TIME_ALERT] intValue]];
225 //Configure the action details pane
226 [self configureDetailsPane];
229 //Save changes made in the details pane
230 - (void)saveDetailsPaneChanges
233 NSDictionary *actionDetails = [detailsPane actionDetails];
235 [alert setObject:actionDetails forKey:KEY_ACTION_DETAILS];
238 //Save our single-fire option
239 [alert setObject:[NSNumber numberWithBool:([checkbox_oneTime state] == NSOnState)] forKey:KEY_ONE_TIME_ALERT];
242 //Remove details view/pane
243 - (void)cleanUpDetailsPane
245 [detailsView removeFromSuperview];
247 [detailsPane closeView];
248 [detailsPane release];
252 //Configure the details pane for our current alert
253 - (void)configureDetailsPane
255 NSString *actionID = [alert objectForKey:KEY_ACTION_ID];
256 id <AIActionHandler> actionHandler = [[[adium contactAlertsController] actionHandlers] objectForKey:actionID];
258 //Save changes and close down the old pane
259 if(detailsPane) [self saveDetailsPaneChanges];
260 [self cleanUpDetailsPane];
262 //Get a new pane for the current action type, and configure it for our alert
263 detailsPane = [[actionHandler detailsPaneForActionID:actionID] retain];
265 NSDictionary *actionDetails = [alert objectForKey:KEY_ACTION_DETAILS];
267 detailsView = [detailsPane view];
269 [detailsPane configureForActionDetails:actionDetails listObject:listObject];
270 [detailsPane configureForEventID:[alert objectForKey:KEY_EVENT_ID]
271 listObject:listObject];
274 //Resize our window for best fit
275 int currentDetailHeight = [view_auxiliary frame].size.height;
276 int desiredDetailHeight = [detailsView frame].size.height;
277 int difference = (currentDetailHeight - desiredDetailHeight);
278 NSRect frame = [[self window] frame];
279 [[self window] setFrame:NSMakeRect(frame.origin.x, frame.origin.y + difference, frame.size.width, frame.size.height - difference)
280 display:[[self window] isVisible]
281 animate:[[self window] isVisible]];
283 //Add the details view
284 if(detailsView) [view_auxiliary addSubview:detailsView];
286 //Pull any default values the pane set in configureForActionDetails
287 [self saveDetailsPaneChanges];
289 //And use them to update our header view
290 [self updateHeaderView];
293 //User selected an event from the popup
294 - (IBAction)selectEvent:(id)sender
297 if((eventID = [sender representedObject])){
298 [alert setObject:eventID forKey:KEY_EVENT_ID];
300 [detailsPane configureForEventID:eventID
301 listObject:listObject];
303 [self updateHeaderView];
307 //User selected an action from the popup
308 - (IBAction)selectAction:(id)sender
310 if([sender representedObject]){
311 NSString *newAction = [sender representedObject];
312 NSString *oldAction = [alert objectForKey:KEY_ACTION_ID];
314 if(![newAction isEqualToString:oldAction]){
315 [alert setObject:[sender representedObject] forKey:KEY_ACTION_ID];
317 [self configureDetailsPane];
322 - (void)alertDetailsForHeaderChanged:(NSNotification *)aNotification
324 [self saveDetailsPaneChanges];
325 [self updateHeaderView];
328 - (void)updateHeaderView
330 NSString *actionID = [alert objectForKey:KEY_ACTION_ID];
331 NSString *eventID = [alert objectForKey:KEY_EVENT_ID];
332 NSString *eventDescription = [[adium contactAlertsController] longDescriptionForEventID:eventID
333 forListObject:listObject];
334 id <AIActionHandler> actionHandler = [[[adium contactAlertsController] actionHandlers] objectForKey:actionID];
336 if(actionHandler && eventDescription){
337 [headerView setStringValue:eventDescription];
338 [headerView setImage:[actionHandler imageForActionID:actionID]];
339 [headerView setSubString:[actionHandler longDescriptionForActionID:actionID
340 withDetails:[alert objectForKey:KEY_ACTION_DETAILS]]];
341 [headerView setNeedsDisplay:YES];